﻿using Ardalis.GuardClauses;
using CleanArchitecture.Core.Configuration;
using CleanArchitecture.Core.Handlers;
using CleanArchitecture.Infrastructure.AutoMapper;
using CleanArchitecture.Infrastructure.Entities;
using CleanArchitecture.Infrastructure.Entities.Business;
using CleanArchitecture.Infrastructure.Entities.Settings;
using CleanArchitecture.Infrastructure.Interfaces;
using CleanArchitecture.Infrastructure.Interfaces.AdminUsers;
using CleanArchitecture.Infrastructure.Interfaces.Business;
using CleanArchitecture.Infrastructure.Interfaces.Security;
using CleanArchitecture.Infrastructure.Interfaces.SystemManage;
using CleanArchitecture.Infrastructure.Models.SystemManage;
using CleanArchitecture.Web.Factories;
using CleanArchitecture.Web.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using NUglify.Helpers;
using NUglify.JavaScript.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CleanArchitecture.Web.Controllers.Backend
{
    public class SystemManageController : BaseAdminController
    {
        private readonly ISystemDataDicService _systemdatadicService;
        private readonly ISystemManageModelFactory _systemmanageFactory;
        private readonly ISystemModuleService _systemmoduleService;
        private readonly IPermissionService _permissionService;
        private readonly IAdminUserService _adminuserService;
        private readonly ISettingService _settingService;

        public SystemManageController(ISystemDataDicService systemdatadicService,
            ISystemManageModelFactory systemmanageFactory,
            ISystemModuleService systemmoduleService,
            IPermissionService permissionService,
            IAdminUserService adminuserService,
            ISettingService settingService)
        {
            this._systemdatadicService = systemdatadicService;
            this._systemmanageFactory = systemmanageFactory;
            this._systemmoduleService = systemmoduleService;
            this._permissionService = permissionService;
            this._adminuserService = adminuserService;
            this._settingService = settingService;
        }
        /// <summary>
        /// 数据字典管理
        /// </summary>
        /// <returns></returns>
        public IActionResult SystemDataDic()
        {
            string moduleUri = BackendAuthorizeRouteConfig.BackendSystem_SystemDataDicManage;
            var CurrentSystemModule = _systemmoduleService.GetSystemModuleByUri(moduleUri);
            if (!_permissionService.Authorize(CurrentSystemModule))
                return AccessDeniedView();
            ViewBag.PageTitle = CurrentSystemModule.DisplayName;
            ViewBag.CurrentSystemModuleId = CurrentSystemModule.Id;
            var searchModel = new SystemDataDicTreeSearchModel();
            searchModel.SetGridPageSize();
            var systemdatadicbtnModel = new SystemDataDicButtonModel();
            searchModel.CustomProperties.Add("datadictreeRoots", _systemdatadicService.GetSystemDataDicTreeByParentId());
            searchModel.CustomProperties.Add("datadicbtnModel", systemdatadicbtnModel);
            return View(searchModel);
        }
        [AuthorizeButton]
        public virtual IActionResult SystemDataDicOrganizeManageEdit(int moduleid, int buttonid, int organizeid = 0)
        {
            ViewBag.PageTitle = "编辑组织机构信息";
            SystemDataDicTreeItemModel organizeModel = null;
            if (organizeid <= 0)
                organizeModel = new SystemDataDicTreeItemModel()
                {//必要数据初始化
                    ParentId = 0,
                    GroupType = EntityEnumConfig.DataDicGroup.Oragnize,
                    DataType = null,
                    IsActive = EntityEnumConfig.YesorNo.YES,
                    DisplayOrder = 1
                };
            else
            {
                var itemEntity = _systemdatadicService.GetDataDicTreeById(organizeid);
                if (itemEntity == null) return PageNotFoundView();
                organizeModel = itemEntity.ToModel<SystemDataDicTreeItemModel>();
            }
            //var dataTypes = Enum.GetValues(typeof(EntityEnumConfig.DataType)).Cast<EntityEnumConfig.DataType>().Where(e => (int)e > 10 && (int)e < 20).ToArray();
            //Array.Sort(dataTypes);
            var AvailableDataTypes = new List<SelectListItem>()
            {
                new SelectListItem("无", "", organizeModel.DataType.HasValue ? false : true)
            };
            //dataTypes.ForEach(type => //根据项目实际情况添加
            //{
            //    string itemName = string.Empty;
            //    switch (type)
            //    {
            //        case EntityEnumConfig.DataType.OrganizeArea:
            //            itemName = "分区经理权限";
            //            break;
            //        case EntityEnumConfig.DataType.OrganizeCenter:
            //            itemName = "站务中心权限";
            //            break;
            //        case EntityEnumConfig.DataType.OrganizePublish:
            //            itemName = "党群中心权限";
            //            break;
            //        case EntityEnumConfig.DataType.OrganizeStation:
            //        default:
            //            itemName = "站点权限";
            //            break;
            //    }
            //    AvailableDataTypes.Add(new SelectListItem(itemName, ((int)type).ToString(), type == organizeModel.DataType ? true : false));
            //});

            ViewBag.AvailableDataTypes = AvailableDataTypes;
            return View(organizeModel);
        }

        /// <summary>
        /// 系统菜单管理
        /// </summary>
        /// <returns></returns>
        [AuthorizeAdmin(AuthorizeType.AdminOnly)]
        public IActionResult SystemModuleManage()
        {
            ViewBag.PageTitle = "系统菜单管理";
            SystemModuleModel model = new SystemModuleModel();
            return View(model);
        }
        /// <summary>
        /// 系统模块修改操作(新增，修改)示图
        /// 按钮操作权限通过对Action方法加入 Attribute Filter方法对按钮是否可操作进行过滤
        /// 详细https://andrewlock.net/using-an-iactionfilter-to-read-action-method-parameter-values-in-asp-net-core-mvc/
        /// </summary>
        /// <param name="action"></param>
        /// <param name="buttonid">按钮权限判断预留，如角色分配系统模块按钮无操作权限，跳转页面至无权限页面</param>
        /// <param name="moduleid"></param>
        /// <returns></returns>
        public IActionResult SystemModuleEditView(int buttonid, int? moduleid)
        {
            ViewBag.PageTitle = "系统菜单管理";
            SystemModuleModel model = PrepareSystemModuleModelForEdit(moduleid);
            return View(model);
        }

        private SystemModuleModel PrepareSystemModuleModelForEdit(int? moduleid)
        {
            SystemModuleModel model = null;
            if (moduleid.HasValue)
                model = _systemmanageFactory.GetSystemModuleModelById(moduleid.Value);
            else model = new SystemModuleModel();
            var datadictreeNodes = _systemmanageFactory.GetSystemDataDicTreesByGroupType(EntityEnumConfig.DataDicGroup.ModuleButton);
            var systemModuleNode = datadictreeNodes.FirstOrDefault(n => n.DataType == EntityEnumConfig.DataType.SystemModule);
            SystemDataDicTreeSearchModel searchModel = new SystemDataDicTreeSearchModel()
            {
                Id = systemModuleNode.Id,
                GroupType = systemModuleNode.GroupType,
                Page = 1,
                PageSize = int.MaxValue
            };
            var buttonModels = _systemmanageFactory.PrepareSystemDataDicButtonListModel(searchModel);
            model.CustomProperties.Add("buttonModels", buttonModels);
            return model;
        }

        /// <summary>
        /// 后台系统菜单权限管理
        /// </summary>
        /// <returns></returns>
        [AuthorizeAdmin(AuthorizeType.AdminOnly)]
        public IActionResult SystemAuthorizeManage()
        {
            ViewBag.PageTitle = "系统菜单权限管理";
            return View();
        }
        /// <summary>
        /// 前端栏目菜单权限管理
        /// </summary>
        /// <returns></returns>
        public IActionResult FrontColumnAuthorizeManage()
        {
            ViewBag.PageTitle = "栏目菜单权限管理";
            //与栏目菜单相关联的模块： 文章管理/博客管理
            //* 注：
            //  偷懒 在此固定获取 文章管理及博客管理 模块的数据库Id,如果Id发生变化，请在此处理
            int[] moduleIds = new int[] { 4 /*文章管理*/, 19 /*博客管理*/};
            var ColumnReferenceModules = new List<SystemModuleModel>();
            moduleIds.ForEach(mid =>
            {
                var itemModels = _systemmanageFactory.GetSystemModuleModelsById(mid);
                if (itemModels != null) ColumnReferenceModules.AddRange(itemModels);
            });
            InitColumnAuthorize(ColumnReferenceModules);
            return View(ColumnReferenceModules);
        }

        /// <summary>
        /// 针对栏目菜单的用户角色权限数据初始化
        /// 文章管理/博客管理基于栏目菜单的功能权限，只针对Setting中ColumnAuthorize为True(即开启栏目权限设置)
        /// 的数据进行数据初始化
        /// </summary>
        /// <param name="ColumnReferenceModules"></param>
        private void InitColumnAuthorize(IList<SystemModuleModel> ColumnReferenceModules)
        {
            try
            {
                Guard.Against.Null(ColumnReferenceModules, nameof(ColumnReferenceModules));
                var roleModels = _adminuserService.GetAdminRoleModelsAll();
                if (roleModels == null) return;
                var columnService = EngineContext.Current.Resolve<IColumnService>();
                var columnModels = columnService.GetColumnList();
                if (columnModels == null) return;
                var rolecolumnMappings = columnService.GetAdminRoleColumnMappingsByRoleIds(roleModels.Select(r => r.Id).ToArray());
                Action<EntityEnumConfig.ColumnType, string> InitColumnAuthorize = (ColumnType, ModuleAssignedButtonIds) => {
                    var mappings = new List<AdminRoleBusColumnMapping>();
                    foreach (var column in columnModels.Where(c => c.ColumnType == ColumnType))
                    {
                        foreach(var role in roleModels)
                        {
                            var mapping = rolecolumnMappings == null
                                        ? null
                                        : rolecolumnMappings.FirstOrDefault(m => m.FKAdminRoleId == role.Id && m.FKColumnId == column.Id);
                            if(mapping == null)
                            {
                                mapping = new AdminRoleBusColumnMapping
                                {
                                    FKAdminRoleId = role.Id,
                                    FKColumnId = column.Id,
                                    AssignedButtonIds = ModuleAssignedButtonIds,
                                    IsAllow = EntityEnumConfig.YesorNo.YES,
                                    AuthorizedButtonIds = ModuleAssignedButtonIds,
                                };
                                mappings.Add(mapping);
                            }
                        }
                    }
                    columnService.InsertAdminRoleColumnAuthorize(mappings);
                };
                NewsSettings newsSettings = null;
                BlogSettings blogSettings = null;
                ColumnReferenceModules.ForEach(itemModel =>
                {
                    if(itemModel.ModuleName.Equals("NewsManage", StringComparison.InvariantCultureIgnoreCase))
                    {
                        newsSettings = EngineContext.Current.Resolve<NewsSettings>();
                        if (newsSettings.ColumnAuthorize)
                            InitColumnAuthorize.Invoke(EntityEnumConfig.ColumnType.NewsColumn, 
                                                       itemModel.ModuleAssignedButtons == null ? string.Empty : string.Join(",", itemModel.ModuleAssignedButtons));
                    }
                    else if(itemModel.ModuleName.Equals("BlogManage", StringComparison.InvariantCultureIgnoreCase))
                    {
                        blogSettings = EngineContext.Current.Resolve<BlogSettings>();
                        if (blogSettings.ColumnAuthorize)
                            InitColumnAuthorize.Invoke(EntityEnumConfig.ColumnType.BlogColumn,
                                                       itemModel.ModuleAssignedButtons == null ? string.Empty : string.Join(",", itemModel.ModuleAssignedButtons));
                    }
                });
            }
            catch (Exception ex)
            {
                if (ex is ArgumentNullException) return;  //Ignore
            }
        }
        #region WebsiteManage
        //[AuthorizeAdmin(AuthorizeType.AdminOnly)]
        public virtual IActionResult WebsiteManage()
        {
            string moduleUri = BackendAuthorizeRouteConfig.BackendSystem_WebsiteManage;
            var CurrentSystemModule = _systemmoduleService.GetSystemModuleByUri(moduleUri);
            if (!_permissionService.Authorize(CurrentSystemModule))
                return AccessDeniedView();
            ViewBag.PageTitle = CurrentSystemModule.DisplayName;
            ViewBag.CurrentSystemModuleId = CurrentSystemModule.Id;
            var websiteNodes = _systemmanageFactory.GetSystemDataDicTreesByGroupType(EntityEnumConfig.DataDicGroup.ClientApp);
            return View(websiteNodes);
        }
        public virtual IActionResult WebsiteManageEdit(int datatype)
        {
            EntityEnumConfig.DataType result = typeof(EntityEnumConfig.DataType).IsEnumDefined(datatype) && datatype >= 100 //过滤非Client(站点)客户端类型
                                             ? (EntityEnumConfig.DataType)datatype
                                             : EntityEnumConfig.DataType.ClientPC; //Default
            ClientSiteSettings clientSettingsModel;
            switch(result)
            {
                case EntityEnumConfig.DataType.ClientMobile:
                    clientSettingsModel = _settingService.LoadSetting<ClientSiteMobileSettings>();
                    break;
                case EntityEnumConfig.DataType.ClientPC:
                default:
                    clientSettingsModel = _settingService.LoadSetting<ClientSitePCSettings>();
                    break;
            }
            ViewBag.DataType = datatype;
            return View(clientSettingsModel);
        }
        #endregion
    }
}